From 625ccdb6b98564d19ccb420e78ce5c38f214ab8d Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Thu, 29 Jul 2004 10:31:20 +0000 Subject: [PATCH] bitkeeper revision 1.1108.24.2 (4108d1f8mh1HwCuBJAKjn8UuBU4wTA) Change to supporting reference to domain by name or id and make xm tools use names. --- tools/python/xen/xend/XendDomain.py | 291 +++++++++-------- tools/python/xen/xend/XendDomainInfo.py | 312 ++++++++++--------- tools/python/xen/xend/server/SrvDomain.py | 108 +++---- tools/python/xen/xend/server/SrvDomainDir.py | 12 +- tools/python/xen/xend/server/blkif.py | 8 +- tools/python/xen/xend/server/controller.py | 6 +- tools/python/xen/xend/server/netif.py | 7 +- tools/python/xen/xend/sxp.py | 3 +- tools/python/xen/xm/create.py | 6 +- tools/python/xen/xm/destroy.py | 6 +- tools/python/xen/xm/main.py | 17 +- tools/python/xen/xm/shutdown.py | 20 +- 12 files changed, 421 insertions(+), 375 deletions(-) diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 1e6a91a244..3a07b49294 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -39,15 +39,23 @@ class XendDomain: dbpath = "domain" """Table of domain info indexed by domain id.""" - domain = {} + domain_by_id = {} + domain_by_name = {} """Table of domains to restart, indexed by domain id.""" - restarts = {} + restarts_by_id = {} + restarts_by_name = {} """Table of delayed calls.""" schedule = {} def __init__(self): + # Hack alert. Python does not support mutual imports, but XendDomainInfo + # needs access to the XendDomain instance to look up domains. Attempting + # to import XendDomain from XendDomainInfo causes unbounded recursion. + # So we stuff the XendDomain instance (self) into XendDomainInfo's + # namespace as 'xd'. + XendDomainInfo.xd = self # Table of domain info indexed by domain id. self.db = XendDB.XendDB(self.dbpath) self.domain_db = self.db.fetchall("") @@ -173,7 +181,8 @@ class XendDomain: @return: deferred """ def cbok(dominfo): - self.domain[dominfo.id] = dominfo + self.domain_by_id[dominfo.id] = dominfo + self.domain_by_name[dominfo.name] = dominfo if dominfo.restart_pending(): self.domain_restart_add(dominfo) @@ -181,17 +190,17 @@ class XendDomain: deferred.addCallback(cbok) return deferred - def _add_domain(self, id, info, notify=1): + def _add_domain(self, info, notify=1): """Add a domain entry to the tables. - @param id: domain id @param info: domain info object @param notify: send a domain created event if true """ - self.domain[id] = info - self.domain_db[id] = info.sxpr() - self.sync_domain(id) - if notify: eserver.inject('xend.domain.created', id) + self.domain_by_id[info.id] = info + self.domain_db[info.id] = info.sxpr() + self.domain_by_name[info.name] = info + self.sync_domain(info.id) + if notify: eserver.inject('xend.domain.created', info.name) def _delete_domain(self, id, notify=1): """Remove a domain from the tables. @@ -199,9 +208,12 @@ class XendDomain: @param id: domain id @param notify: send a domain died event if true """ - if id in self.domain: - if notify: eserver.inject('xend.domain.died', id) - del self.domain[id] + if id in self.domain_by_id: + info = self.domain_by_id[id] + if notify: eserver.inject('xend.domain.died', info.name) + if info.name in self.domain_by_name: + del self.domain_by_name[info.name] + del self.domain_by_id[id] if id in self.domain_db: del self.domain_db[id] self.db.delete(id) @@ -229,7 +241,7 @@ class XendDomain: if reason in ['poweroff', 'reboot']: self.domain_restart_schedule(id, reason) self.final_domain_destroy(id) - if len(self.restarts): + if self.domain_restarts_exist(): self.domain_restarts_schedule() def refresh(self): @@ -243,14 +255,14 @@ class XendDomain: for d in domlist: id = str(d['dom']) doms[id] = d - if id not in self.domain: + if id not in self.domain_by_id: savedinfo = None deferred = XendDomainInfo.vm_recreate(savedinfo, d) def cbok(dominfo): - self._add_domain(dominfo.id, dominfo) + self._add_domain(dominfo) deferred.addCallback(cbok) # Remove entries for domains that no longer exist. - for d in self.domain.values(): + for d in self.domain_by_id.values(): info = doms.get(d.id) if info: d.update(info) @@ -263,7 +275,7 @@ class XendDomain: @param id: domain id """ - dominfo = self.domain.get(id) + dominfo = self.domain_by_id.get(id) if dominfo: self.domain_db[id] = dominfo.sxpr() self.sync_domain(id) @@ -283,17 +295,25 @@ class XendDomain: raise pass else: - d = self.domain.get(id) + d = self.domain_by_id.get(id) if d: d.update(dominfo[0]) def domain_ls(self): + """Get list of domain names. + + @return: domain names + """ + self.refresh() + return self.domain_by_name.keys() + + def domain_ls_ids(self): """Get list of domain ids. - @return: domain ids + @return: domain names """ self.refresh() - return self.domain.keys() + return self.domain_by_id.keys() def domains(self): """Get list of domain objects. @@ -301,7 +321,7 @@ class XendDomain: @return: domain objects """ self.refresh() - return self.domain.values() + return self.domain_by_id.values() def domain_create(self, config): """Create a domain from a configuration. @@ -310,7 +330,7 @@ class XendDomain: @return: deferred """ def cbok(dominfo): - self._add_domain(dominfo.id, dominfo) + self._add_domain(dominfo) return dominfo deferred = XendDomainInfo.vm_create(config) deferred.addCallback(cbok) @@ -323,7 +343,7 @@ class XendDomain: @return: deferred """ def cbok(dominfo): - self._add_domain(dominfo.id, dominfo) + self._add_domain(dominfo) return dominfo log.info("Restarting domain: id=%s name=%s", dominfo.id, dominfo.name) deferred = dominfo.restart() @@ -338,15 +358,14 @@ class XendDomain: @param config: configuration @return: deferred """ - log.debug('domain_configure> id=%s config=%s', id, str(config)) - dom = int(id) - dominfo = self.domain_get(dom) + dominfo = self.domain_get(id) if not dominfo: raise XendError("Invalid domain: " + str(id)) + log.debug('domain_configure> id=%s config=%s', id, str(config)) if dominfo.config: - raise XendError("Domain already configured: " + str(id)) + raise XendError("Domain already configured: " + dominfo.name) def cbok(dominfo): - self._add_domain(dominfo.id, dominfo) + self._add_domain(dominfo) return dominfo deferred = dominfo.construct(config) deferred.addCallback(cbok) @@ -361,7 +380,7 @@ class XendDomain: """ def cbok(dominfo): - self._add_domain(dominfo.id, dominfo) + self._add_domain(dominfo) return dominfo deferred = XendDomainInfo.vm_restore(src, progress=progress) deferred.addCallback(cbok) @@ -375,25 +394,39 @@ class XendDomain: """ id = str(id) self.refresh_domain(id) - return self.domain.get(id) - + return self.domain_by_id.get(id) + + def domain_lookup(self, name): + name = str(name) + dominfo = self.domain_by_name.get(name) or self.domain_by_id.get(name) + if dominfo: + return dominfo + raise XendError('invalid domain:' + name) + + def domain_exists(self, name): + name = str(name) + if self.domain_by_name.get(name) or self.domain_by_id.get(name): + return 1 + else: + return 0 + def domain_unpause(self, id): """Unpause domain execution. @param id: domain id """ - dom = int(id) - eserver.inject('xend.domain.unpause', id) - return xc.domain_unpause(dom=dom) + dominfo = self.domain_lookup(id) + eserver.inject('xend.domain.unpause', dominfo.name) + return xc.domain_unpause(dom=dominfo.dom) def domain_pause(self, id): """Pause domain execution. @param id: domain id """ - dom = int(id) - eserver.inject('xend.domain.pause', id) - return xc.domain_pause(dom=dom) + dominfo = self.domain_lookup(id) + eserver.inject('xend.domain.pause', dominfo.name) + return xc.domain_pause(dom=dominfo.dom) def domain_shutdown(self, id, reason='poweroff'): """Shutdown domain (nicely). @@ -406,18 +439,15 @@ class XendDomain: @param id: domain id @param reason: shutdown type: poweroff, reboot, suspend, halt """ - dom = int(id) - id = str(id) - if dom <= 0: - return 0 + dominfo = self.domain_lookup(id) if reason == 'halt': - self.domain_restart_cancel(id) + self.domain_restart_cancel(dominfo.id) else: - self.domain_restart_schedule(id, reason, force=1) - eserver.inject('xend.domain.shutdown', [id, reason]) + self.domain_restart_schedule(dominfo.id, reason, force=1) + eserver.inject('xend.domain.shutdown', [dominfo.name, reason]) if reason == 'halt': reason = 'poweroff' - val = xend.domain_shutdown(dom, reason) + val = xend.domain_shutdown(dominfo.id, reason) self.refresh_schedule() return val @@ -428,10 +458,10 @@ class XendDomain: @param reason: shutdown reason """ log.debug('domain_restart_schedule> %s %s %d', id, reason, force) - dominfo = self.domain.get(id) + dominfo = self.domain_lookup(id) if not dominfo: return - if id in self.restarts: + if dominfo.id in self.restarts_by_id: return restart = (force and reason == 'reboot') or dominfo.restart_needed(reason) if restart: @@ -439,8 +469,9 @@ class XendDomain: self.domain_restart_add(dominfo) def domain_restart_add(self, dominfo): - self.restarts[dominfo.id] = dominfo - log.info('Scheduling restart for domain: id=%s name=%s', dominfo.id, dominfo.name) + self.restarts_by_name[dominfo.name] = dominfo + self.restarts_by_id[dominfo.id] = dominfo + log.info('Scheduling restart for domain: name=%s id=%s', dominfo.name, dominfo.id) self.domain_restarts_schedule() def domain_restart_cancel(self, id): @@ -448,53 +479,57 @@ class XendDomain: @param id: domain id """ - dominfo = self.restarts.get(id) + dominfo = self.restarts_by_id.get(id) or self.restarts_by_name.get(id) if dominfo: - log.info('Cancelling restart for domain: id=%s name=%s', dominfo.id, dominfo.name) + log.info('Cancelling restart for domain: name=%s id=%s', dominfo.name, dominfo.id) dominfo.restart_cancel() - del self.restarts[id] + del self.restarts_by_id[dominfo.id] + del self.restarts_by_name[dominfo.name] def domain_restarts(self): """Execute any scheduled domain restarts for domains that have gone. """ self.domain_restarts_cancel() - for id in self.restarts.keys(): - if id in self.domain: + for dominfo in self.restarts_by_id.values(): + if dominfo.id in self.domain_by_id: # Don't execute restart for domains still running. continue - dominfo = self.restarts[id] # Remove it from the restarts. - del self.restarts[id] + del self.restarts_by_id[dominfo.id] + del self.restarts_by_name[dominfo.name] try: def cbok(dominfo): - log.info('Restarted domain id=%s as %s', id, dominfo.id) + log.info('Restarted domain name=%s id=%s', dominfo.name, dominfo.id) self.domain_unpause(dominfo.id) def cberr(err): - log.exception("Delayed exception restarting domain: id=%s", id) + log.exception("Delayed exception restarting domain: name=%s id=%s", + dominfo.name, dominfo.id) deferred = self.domain_restart(dominfo) deferred.addCallback(cbok) deferred.addErrback(cberr) except: - log.exception("Exception restarting domain: id=%s", id) - if len(self.restarts): + log.exception("Exception restarting domain: name=%s id=%s", + dominfo.name, dominfo.id) + if self.domain_restarts_exist(): # Run again later if any restarts remain. self.refresh_schedule(delay=5) + + def domain_restarts_exist(self): + return len(self.restarts_by_id) def final_domain_destroy(self, id): """Final destruction of a domain.. @param id: domain id """ - dom = int(id) - if dom <= 0: - return 0 - log.info('Destroying domain: id=%s', str(id)) - eserver.inject('xend.domain.destroy', id) - dominfo = self.domain.get(id) + dominfo = self.domain_lookup(id) + log.info('Destroying domain: name=%s', dominfo.name) + eserver.inject('xend.domain.destroy', dominfo.name) if dominfo: val = dominfo.destroy() else: - val = xc.domain_destroy(dom=dom) + #todo + val = xc.domain_destroy(dom=dominfo.dom) return val def domain_destroy(self, id, reason='halt'): @@ -504,7 +539,6 @@ class XendDomain: @param id: domain id """ - id = str(id) if reason == 'halt': self.domain_restart_cancel(id) elif reason == 'reboot': @@ -522,9 +556,9 @@ class XendDomain: # Need a cancel too? # Don't forget to cancel restart for it. print 'domain_migrate>', id, dst - dom = int(id) + dominfo = self.domain_lookup(id) xmigrate = XendMigrate.instance() - val = xmigrate.migrate_begin(dom, dst) + val = xmigrate.migrate_begin(dominfo.id, dst) print 'domain_migrate<', val return val @@ -536,9 +570,9 @@ class XendDomain: @param progress: output progress if true @return: deferred """ - dom = int(id) + dominfo = self.domain_lookup(id) xmigrate = XendMigrate.instance() - return xmigrate.save_begin(dom, dst) + return xmigrate.save_begin(dominfo.id, dst) def domain_pincpu(self, dom, cpu): """Pin a domain to a cpu. @@ -546,156 +580,149 @@ class XendDomain: @param dom: domain @param cpu: cpu number """ - dom = int(dom) - return xc.domain_pincpu(dom, cpu) + dominfo = self.domain_lookup(id) + return xc.domain_pincpu(itn(dominfo.id), cpu) - def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu): + def domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu): """Set BVT (Borrowed Virtual Time) scheduler parameters for a domain. """ - dom = int(dom) - return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv, + dominfo = self.domain_lookup(id) + return xc.bvtsched_domain_set(dom=dominfo.dom, mcuadv=mcuadv, warp=warp, warpl=warpl, warpu=warpu) - def domain_cpu_bvt_get(self, dom): + def domain_cpu_bvt_get(self, id): """Get BVT (Borrowed Virtual Time) scheduler parameters for a domain. """ - dom = int(dom) - return xc.bvtsched_domain_get(dom) + dominfo = self.domain_lookup(id) + return xc.bvtsched_domain_get(dominfo.dom) - def domain_cpu_fbvt_set(self, dom, mcuadv, warp, warpl, warpu): + def domain_cpu_fbvt_set(self, id, mcuadv, warp, warpl, warpu): """Set FBVT (Fair Borrowed Virtual Time) scheduler parameters for a domain. """ - dom = int(dom) - return xc.fbvtsched_domain_set(dom=dom, mcuadv=mcuadv, + dominfo = self.domain_lookup(id) + return xc.fbvtsched_domain_set(dom=dominfo.dom, mcuadv=mcuadv, warp=warp, warpl=warpl, warpu=warpu) - def domain_cpu_fbvt_get(self, dom): + def domain_cpu_fbvt_get(self, id): """Get FBVT (Fair Borrowed Virtual Time) scheduler parameters for a domain. """ - dom = int(dom) - return xc.fbvtsched_domain_get(dom) + dominfo = self.domain_lookup(id) + return xc.fbvtsched_domain_get(dominfo.dom) - def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime): + def domain_cpu_atropos_set(self, id, period, slice, latency, xtratime): """Set Atropos scheduler parameters for a domain. """ - dom = int(dom) - return xc.atropos_domain_set(dom, period, slice, latency, xtratime) + dominfo = self.domain_lookup(id) + return xc.atropos_domain_set(dominfo.dom, period, slice, latency, xtratime) - def domain_cpu_atropos_get(self, dom): + def domain_cpu_atropos_get(self, id): """Get Atropos scheduler parameters for a domain. """ - dom = int(dom) - return xc.atropos_domain_get(dom) + dominfo = self.domain_lookup(id) + return xc.atropos_domain_get(dominfo.dom) - def domain_device_create(self, dom, devconfig): + def domain_device_create(self, id, devconfig): """Create a new device for a domain. - @param dom: domain id + @param id: domain id @param devconfig: device configuration @return: deferred """ - dom = int(dom) - dominfo = self.domain_get(dom) - if not dominfo: - raise XendError("invalid domain:" + str(dom)) + dominfo = self.domain_lookup(id) self.refresh_schedule() val = dominfo.device_create(devconfig) self.update_domain(dominfo.id) return val - def domain_device_destroy(self, dom, type, idx): + def domain_device_destroy(self, id, type, idx): """Destroy a device. - @param dom: domain id + @param id: domain id @param type: device type @param idx: device index """ - dom = int(dom) - dominfo = self.domain_get(dom) - if not dominfo: - raise XendError("invalid domain:" + str(dom)) + dominfo = self.domain_lookup(id) self.refresh_schedule() val = dominfo.device_destroy(type, idx) self.update_domain(dominfo.id) return val - def domain_devtype_ls(self, dom, type): + def domain_devtype_ls(self, id, type): """Get list of device indexes for a domain. - @param dom: domain + @param id: domain @param type: device type @return: device indexes """ - dominfo = self.domain_get(dom) - if not dominfo: return None + dominfo = self.domain_lookup(id) devs = dominfo.get_devices(type) - return range(0, len(devs)) + #return range(0, len(devs)) + return devs - def domain_devtype_get(self, dom, type, idx): + def domain_devtype_get(self, id, type, idx): """Get a device from a domain. - @param dom: domain + @param id: domain @param type: device type @param idx: device index @return: device object (or None) """ - dominfo = self.domain_get(dom) - if not dominfo: return None + dominfo = self.domain_lookup(id) return dominfo.get_device_by_index(type, idx) - def domain_vif_ls(self, dom): + def domain_vif_ls(self, id): """Get list of virtual network interface (vif) indexes for a domain. - @param dom: domain + @param id: domain @return: vif indexes """ - return self.domain_devtype_ls(dom, 'vif') + return self.domain_devtype_ls(id, 'vif') - def domain_vif_get(self, dom, vif): + def domain_vif_get(self, id, vif): """Get a virtual network interface (vif) from a domain. - @param dom: domain + @param id: domain @param vif: vif index @return: vif device object (or None) """ - return self.domain_devtype_get(dom, 'vif', vif) + return self.domain_devtype_get(id, 'vif', vif) - def domain_vbd_ls(self, dom): + def domain_vbd_ls(self, id): """Get list of virtual block device (vbd) indexes for a domain. - @param dom: domain + @param id: domain @return: vbd indexes """ - return self.domain_devtype_ls(dom, 'vbd') + return self.domain_devtype_ls(id, 'vbd') - def domain_vbd_get(self, dom, vbd): + def domain_vbd_get(self, id, vbd): """Get a virtual block device (vbd) from a domain. - @param dom: domain + @param id: domain @param vbd: vbd index @return: vbd device (or None) """ - return self.domain_devtype_get(dom, 'vbd', vbd) + return self.domain_devtype_get(id, 'vbd', vbd) - def domain_shadow_control(self, dom, op): + def domain_shadow_control(self, id, op): """Shadow page control. - @param dom: domain + @param id: domain @param op: operation """ - dom = int(dom) - return xc.shadow_control(dom, op) + dominfo = self.domain_lookup(id) + return xc.shadow_control(dominfo.dom, op) - def domain_maxmem_set(self, dom, mem): + def domain_maxmem_set(self, id, mem): """Set the memory limit for a domain. @param dom: domain @param mem: memory limit (in MB) @return: 0 on success, -1 on error """ - dom = int(dom) + dominfo = self.domain_lookup(id) maxmem = int(mem) * 1024 - return xc.domain_setmaxmem(dom, maxmem_kb = maxmem) + return xc.domain_setmaxmem(dominfo.dom, maxmem_kb = maxmem) def instance(): diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 9d7dfe325c..1a9b74190a 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -193,8 +193,8 @@ config_handlers = {} def add_config_handler(name, h): """Add a handler for a config field. - name field name - h handler: fn(vm, config, field, index) + @param name: field name + @param h: handler: fn(vm, config, field, index) """ config_handlers[name] = h @@ -212,16 +212,15 @@ image_handlers = {} def add_image_handler(name, h): """Add a handler for an image type - name image type - h handler: fn(config, name, memory, image) + @param name: image type + @param h: handler: fn(config, name, memory, image) """ image_handlers[name] = h def get_image_handler(name): """Get the handler for an image type. - name image type - - returns handler or None + @param name: image type + @return: handler or None """ return image_handlers.get(name) @@ -233,17 +232,16 @@ device_handlers = {} def add_device_handler(name, h): """Add a handler for a device type. - name device type - h handler: fn(vm, dev) + @param name: device type + @param h: handler: fn(vm, dev) """ device_handlers[name] = h def get_device_handler(name): """Get the handler for a device type. - name device type - - returns handler or None + @param name : device type + @return; handler or None """ return device_handlers.get(name) @@ -252,10 +250,9 @@ def vm_create(config): If a vm has been partially created and there is an error it is destroyed. - config configuration - - returns Deferred - raises VmError for invalid configuration + @param config configuration + @return: Deferred + @raise: VmError for invalid configuration """ vm = XendDomainInfo() return vm.construct(config) @@ -314,21 +311,27 @@ def vm_restore(src, progress=0): return deferred def dom_get(dom): + """Get info from xen for an existing domain. + + @param dom: domain id + @return: info or None + """ domlist = xc.domain_getinfo(dom=dom) if domlist and dom == domlist[0]['dom']: return domlist[0] return None - def append_deferred(dlist, v): + """Append a value to a deferred list if it is a deferred. + + @param dlist: list of deferreds + @param v: value to add + """ if isinstance(v, defer.Deferred): dlist.append(v) def _vm_configure1(val, vm): d = vm.create_devices() - def cbok(x): - return x - d.addCallback(cbok) d.addCallback(_vm_configure2, vm) return d @@ -348,7 +351,7 @@ class XendDomainInfo: """Minimum time between domain restarts in seconds. """ - MINIMUM_RESTART_TIME = 10 + MINIMUM_RESTART_TIME = 20 def __init__(self): self.recreate = 0 @@ -363,6 +366,7 @@ class XendDomainInfo: self.cmdline = None self.console = None self.devices = {} + self.device_index = {} self.configs = [] self.info = None self.ipaddrs = [] @@ -378,9 +382,13 @@ class XendDomainInfo: self.console_port = None def setdom(self, dom): + """Set the domain id. + + @param dom: domain id + """ self.dom = int(dom) self.id = str(dom) - + def update(self, info): """Update with info from xc.domain_getinfo(). """ @@ -437,13 +445,39 @@ class XendDomainInfo: sxpr.append(['config', self.config]) return sxpr + def check_name(self, name): + """Check if a vm name is valid. Valid names start with a non-digit + and contain alphabetic characters, digits, or characters in '_-.'. + The same name cannot be used for more than one vm at the same time. + + @param name: name + @raise: VMerror if invalid + """ + if name is None or name == '': + raise VmError('missing vm name') + if name[0] in string.digits: + raise VmError('invalid vm name') + for c in name: + if c in string.digits: continue + if c in '_-.': continue + if c in string.ascii_letters: continue + raise VmError('invalid vm name') + # See comment in XendDomain constructor about 'xd'. + if xd.domain_exists(name): + raise VmError('vm name clash: ' + name) + def construct(self, config): + """Construct the vm instance from its configuration. + + @param config: configuration + @return: deferred + @raise: VmError on error + """ # todo - add support for scheduling params? self.config = config try: self.name = sxp.child_value(config, 'name') - if self.name is None: - raise VmError('missing domain name') + self.check_name(self.name) self.memory = int(sxp.child_value(config, 'memory')) if self.memory is None: raise VmError('missing memory size') @@ -462,12 +496,9 @@ class XendDomainInfo: raise VmError('unknown image type: ' + image_name) image_handler(self, image) deferred = self.configure() - def cbok(x): - return x def cberr(err): self.destroy() return err - deferred.addCallback(cbok) deferred.addErrback(cberr) except StandardError, ex: # Catch errors, cleanup and re-raise. @@ -478,8 +509,10 @@ class XendDomainInfo: def config_devices(self, name): """Get a list of the 'device' nodes of a given type from the config. - name device type - return list of device configs + @param name: device type + @type name: string + @return: device configs + @rtype: list """ devices = [] for d in sxp.children(self.config, 'device'): @@ -490,31 +523,57 @@ class XendDomainInfo: return devices def config_device(self, type, idx): + """Get a device config from the device nodes of a given type + from the config. + + @param type: device type + @type type: string + @param idx: index + @type idx: int + @return config or None + """ devs = self.config_devices(type) if 0 <= idx < len(devs): return devs[idx] else: return None + def next_device_index(self, type): + """Get the next index for a given device type. + + @param type: device type + @type type: string + @return device index + @rtype: int + """ + idx = self.device_index.get(type, 0) + self.device_index[type] = idx + 1 + return idx + def add_device(self, type, dev): """Add a device to a virtual machine. - dev device to add + @param type: device type + @param dev: device to add """ dl = self.devices.get(type, []) dl.append(dev) self.devices[type] = dl def get_devices(self, type): + """Get a list of the devices of a given type. + + @param type: device type + @return: devices + """ val = self.devices.get(type, []) return val def get_device_by_id(self, type, id): """Get the device with the given id. - id device id - - returns device or None + @param id: device id + @return: device or None """ dl = self.get_devices(type) for d in dl: @@ -525,20 +584,20 @@ class XendDomainInfo: def get_device_by_index(self, type, idx): """Get the device with the given index. - idx device index - - returns device or None + @param idx: device index + @return: device or None """ + idx = str(idx) dl = self.get_devices(type) - if 0 <= idx < len(dl): - return dl[idx] - else: - return None + for d in dl: + if d.getidx() == idx: + return d + return None def add_config(self, val): """Add configuration data to a virtual machine. - val data to add + @param val: data to add """ self.configs.append(val) @@ -661,11 +720,11 @@ class XendDomainInfo: def create_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n): """Create a domain. Builds the image but does not configure it. - ostype OS type - kernel kernel image - ramdisk kernel ramdisk - cmdline kernel commandline - vifs_n number of network interfaces + @param ostype: OS type + @param kernel: kernel image + @param ramdisk: kernel ramdisk + @param cmdline: kernel commandline + @param vifs_n: number of network interfaces """ if not self.recreate: if not os.path.isfile(kernel): @@ -685,8 +744,8 @@ class XendDomainInfo: def create_devices(self): """Create the devices for a vm. - returns Deferred - raises VmError for invalid devices + @return: Deferred + @raise: VmError for invalid devices """ dlist = [] devices = sxp.children(self.config, 'device') @@ -730,16 +789,17 @@ class XendDomainInfo: """ dev = self.get_device_by_index(type, idx) if not dev: - raise VmError('invalid device: %s %d' % (type, idx)) + raise VmError('invalid device: %s %s' % (type, idx)) devs = self.devices.get(type) - if 0 <= idx < len(devs): - del devs[idx] - dev_config = self.config_device(type, idx) + index = devs.index(dev) + dev_config = self.config_device(type, index) if dev_config: self.config.remove(['device', dev_config]) dev.destroy() def configure_console(self): + """Configure the vm console port. + """ x = sxp.child_value(self.config, 'console') if x: try: @@ -749,12 +809,20 @@ class XendDomainInfo: self.console_port = port def configure_restart(self): + """Configure the vm restart mode. + """ r = sxp.child_value(self.config, 'restart', RESTART_ONREBOOT) if r not in restart_modes: raise VmError('invalid restart mode: ' + str(r)) self.restart_mode = r; def restart_needed(self, reason): + """Determine if the vm needs to be restarted when shutdown + for the given reason. + + @param reason: shutdown reason + @return 1 if needs restaert, 0 otherwise + """ if self.restart_mode == RESTART_NEVER: return 0 if self.restart_mode == RESTART_ALWAYS: @@ -764,12 +832,18 @@ class XendDomainInfo: return 0 def restart_cancel(self): + """Cancel a vm restart. + """ self.restart_state = None def restarting(self): + """Put the vm into restart mode. + """ self.restart_state = STATE_RESTART_PENDING def restart_pending(self): + """Test if the vm has a pending restart. + """ return self.restart_state == STATE_RESTART_PENDING def restart_check(self): @@ -781,7 +855,7 @@ class XendDomainInfo: if self.restart_time is not None: tdelta = tnow - self.restart_time if tdelta < self.MINIMUM_RESTART_TIME: - msg = 'VM %d restarting too fast' % self.dom + msg = 'VM %s restarting too fast' % self.name log.error(msg) raise VmError(msg) self.restart_time = tnow @@ -830,17 +904,17 @@ class XendDomainInfo: """ if self.blkif_backend: d = defer.Deferred() - d.callback(1) + d.callback(self) else: d = xend.blkif_create(self.dom, recreate=self.recreate) d.addCallback(_vm_configure1, self) return d def dom_configure(self, dom): - """Configure a domain. + """Configure a vm for an existing domain. - dom domain id - returns deferred + @param dom: domain id + @return: deferred """ d = dom_get(dom) if not d: @@ -860,6 +934,8 @@ class XendDomainInfo: return deferred def configure_fields(self): + """Process the vm configuration fields using the registered handlers. + """ dlist = [] index = {} for field in sxp.children(self.config): @@ -880,11 +956,10 @@ class XendDomainInfo: def vm_image_linux(vm, image): """Create a VM for a linux image. - name vm name - memory vm memory - image image config - - returns vm + @param name: vm name + @param memory: vm memory + @param image: image config + @return: vm """ kernel = sxp.child_value(image, "kernel") cmdline = "" @@ -905,11 +980,10 @@ def vm_image_linux(vm, image): def vm_image_netbsd(vm, image): """Create a VM for a bsd image. - name vm name - memory vm memory - image image config - - returns vm + @param name: vm name + @param memory: vm memory + @param image: image config + @return: vm """ #todo: Same as for linux. Is that right? If so can unify them. kernel = sxp.child_value(image, "kernel") @@ -932,13 +1006,14 @@ def vm_image_netbsd(vm, image): def vm_dev_vif(vm, val, index): """Create a virtual network interface (vif). - vm virtual machine - val vif config - index vif index + @param vm: virtual machine + @param val: vif config + @param index: vif index + @return: deferred """ if vm.netif_backend: raise VmError('vif: vif in netif backend domain') - vif = index #todo + vif = vm.next_device_index('vif') vmac = sxp.child_value(val, "mac") xend.netif_create(vm.dom, recreate=vm.recreate) log.debug("Creating vif dom=%d vif=%d mac=%s", vm.dom, vif, str(vmac)) @@ -954,13 +1029,14 @@ def vm_dev_vif(vm, val, index): def vm_dev_vbd(vm, val, index): """Create a virtual block device (vbd). - vm virtual machine - val vbd config - index vbd index + @param vm: virtual machine + @param val: vbd config + @param index: vbd index + @return: deferred """ if vm.blkif_backend: raise VmError('vbd: vbd in blkif backend domain') - vdev = index + vdev = vm.next_device_index('vif') uname = sxp.child_value(val, 'uname') if not uname: raise VmError('vbd: Missing uname') @@ -978,6 +1054,8 @@ def vm_dev_vbd(vm, val, index): return defer def parse_pci(val): + """Parse a pci field. + """ if isinstance(val, types.StringType): radix = 10 if val.startswith('0x') or val.startswith('0X'): @@ -988,6 +1066,13 @@ def parse_pci(val): return v def vm_dev_pci(vm, val, index): + """Add a pci device. + + @param vm: virtual machine + @param val: device configuration + @param index: device index + @return: 0 on success + """ bus = sxp.child_value(val, 'bus') if not bus: raise VmError('pci: Missing bus') @@ -1013,78 +1098,21 @@ def vm_dev_pci(vm, val, index): return rc -def vm_field_vfr(vm, config, val, index): - """Handle a vfr field in a config. - - vm virtual machine - config vm config - val vfr field - """ - # Get the rules and add them. - # (vfr (vif (id foo) (ip x.x.x.x)) ... ) - list = sxp.children(val, 'vif') - ipaddrs = [] - for v in list: - id = sxp.child_value(v, 'id') - if id is None: - raise VmError('vfr: missing vif id') - id = int(id) - dev = vm.get_device_by_index('vif', id) - if not dev: - raise VmError('vfr: invalid vif id %d' % id) - vif = sxp.child_value(dev, 'vif') - ip = sxp.child_value(v, 'ip') - if not ip: - raise VmError('vfr: missing ip address') - ipaddrs.append(ip); - # todo: Configure the ipaddrs. - vm.ipaddrs = ipaddrs - -def vnet_bridge(vnet, vmac, dom, idx): - """Add the device for the vif to the bridge for its vnet. - """ - vif = "vif%d.%d" % (dom, idx) - try: - cmd = "(vif.conn (vif %s) (vnet %s) (vmac %s))" % (vif, vnet, vmac) - log.debug("vnet_bridge> %s", cmd) - out = file("/proc/vnet/policy", "wb") - out.write(cmd) - err = out.close() - log.debug("vnet_bridge> err=%d", err) - except IOError, ex: - log.exception("vnet_bridge>") - -def vm_field_vnet(vm, config, val, index): - """Handle a vnet field in a config. +def vm_field_ignore(vm, config, val, index): + """Dummy config field handler used for fields with built-in handling. - vm virtual machine - config vm config - val vnet field - index index + @param vm: virtual machine + @param config: vm config + @param val: vfr field + @param index: field index """ - # Get the vif children. For each vif look up the vif device - # with the given id and configure its vnet. - # (vnet (vif (id foo) (vnet 2) (mac x:x:x:x:x:x)) ... ) - vif_vnets = sxp.children(val, 'vif') - for v in vif_vnets: - id = sxp.child_value(v, 'id') - if id is None: - raise VmError('vnet: missing vif id') - dev = vm.get_device_by_id('vif', id) - #vnet = sxp.child_value(v, 'vnet', 1) - #mac = sxp.child_value(dev, 'mac') - #vif = sxp.child_value(dev, 'vif') - #vnet_bridge(vnet, mac, vm.dom, 0) - #vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]]) - -def vm_field_ignore(vm, config, val, index): pass -# Register image handlers for linux and bsd. +# Register image handlers. add_image_handler('linux', vm_image_linux) add_image_handler('netbsd', vm_image_netbsd) -# Register device handlers for vifs and vbds. +# Register device handlers. add_device_handler('vif', vm_dev_vif) add_device_handler('vbd', vm_dev_vbd) add_device_handler('pci', vm_dev_pci) @@ -1098,6 +1126,4 @@ add_config_handler('image', vm_field_ignore) add_config_handler('device', vm_field_ignore) add_config_handler('backend', vm_field_ignore) -# Register config handlers for vfr and vnet. -add_config_handler('vfr', vm_field_vfr) -add_config_handler('vnet', vm_field_vnet) +# Register other config handlers. diff --git a/tools/python/xen/xend/server/SrvDomain.py b/tools/python/xen/xend/server/SrvDomain.py index 886021ee75..7b398a3606 100644 --- a/tools/python/xen/xend/server/SrvDomain.py +++ b/tools/python/xen/xend/server/SrvDomain.py @@ -22,9 +22,9 @@ class SrvDomain(SrvDir): def op_configure(self, op, req): fn = FormFn(self.xd.domain_configure, - [['dom', 'int'], + [['dom', 'str'], ['config', 'sxpr']]) - deferred = fn(req.args, {'dom': self.dom.id}) + deferred = fn(req.args, {'dom': self.dom.name}) deferred.addErrback(self._op_configure_err, req) return deferred @@ -33,35 +33,35 @@ class SrvDomain(SrvDir): return str(err) def op_unpause(self, op, req): - val = self.xd.domain_unpause(self.dom.id) + val = self.xd.domain_unpause(self.dom.name) return val def op_pause(self, op, req): - val = self.xd.domain_pause(self.dom.id) + val = self.xd.domain_pause(self.dom.name) return val def op_shutdown(self, op, req): fn = FormFn(self.xd.domain_shutdown, - [['dom', 'int'], + [['dom', 'str'], ['reason', 'str']]) - val = fn(req.args, {'dom': self.dom.id}) + val = fn(req.args, {'dom': self.dom.name}) req.setResponseCode(http.ACCEPTED) req.setHeader("Location", "%s/.." % req.prePathURL()) return val def op_destroy(self, op, req): fn = FormFn(self.xd.domain_destroy, - [['dom', 'int'], + [['dom', 'str'], ['reason', 'str']]) - val = fn(req.args, {'dom': self.dom.id}) + val = fn(req.args, {'dom': self.dom.name}) req.setHeader("Location", "%s/.." % req.prePathURL()) return val def op_save(self, op, req): fn = FormFn(self.xd.domain_save, - [['dom', 'int'], + [['dom', 'str'], ['file', 'str']]) - deferred = fn(req.args, {'dom': self.dom.id}) + deferred = fn(req.args, {'dom': self.dom.name}) deferred.addCallback(self._op_save_cb, req) deferred.addErrback(self._op_save_err, req) return deferred @@ -75,9 +75,9 @@ class SrvDomain(SrvDir): def op_migrate(self, op, req): fn = FormFn(self.xd.domain_migrate, - [['dom', 'int'], + [['dom', 'str'], ['destination', 'str']]) - deferred = fn(req.args, {'dom': self.dom.id}) + deferred = fn(req.args, {'dom': self.dom.name}) print 'op_migrate>', deferred deferred.addCallback(self._op_migrate_cb, req) deferred.addErrback(self._op_migrate_err, req) @@ -99,99 +99,85 @@ class SrvDomain(SrvDir): req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err)) return str(err) - def op_device_create(self, op, req): - fn = FormFn(self.xd.domain_device_create, - [['dom', 'int'], - ['config', 'sxpr']]) - d = fn(req.args, {'dom': self.dom.id}) - return d - - def op_device_destroy(self, op, req): - fn = FormFn(self.xd.domain_device_destroy, - [['dom', 'int'], - ['type', 'str'], - ['index', 'int']]) - val = fn(req.args, {'dom': self.dom.id}) - return val - def op_pincpu(self, op, req): fn = FormFn(self.xd.domain_pincpu, - [['dom', 'int'], + [['dom', 'str'], ['cpu', 'int']]) - val = fn(req.args, {'dom': self.dom.id}) + val = fn(req.args, {'dom': self.dom.name}) return val def op_cpu_bvt_set(self, op, req): fn = FormFn(self.xd.domain_cpu_bvt_set, - [['dom', 'int'], + [['dom', 'str'], ['mcuadv', 'int'], ['warp', 'int'], ['warpl', 'int'], ['warpu', 'int']]) - val = fn(req.args, {'dom': self.dom.id}) + val = fn(req.args, {'dom': self.dom.name}) return val def op_cpu_fbvt_set(self, op, req): fn = FormFn(self.xd.domain_cpu_fbvt_set, - [['dom', 'int'], + [['dom', 'str'], ['mcuadv', 'int'], ['warp', 'int'], ['warpl', 'int'], ['warpu', 'int']]) - val = fn(req.args, {'dom': self.dom.id}) + val = fn(req.args, {'dom': self.dom.name}) return val def op_cpu_atropos_set(self, op, req): fn = FormFn(self.xd.domain_cpu_atropos_set, - [['dom', 'int'], + [['dom', 'str'], ['period', 'int'], ['slice', 'int'], ['latency', 'int'], ['xtratime', 'int']]) - val = fn(req.args, {'dom': self.dom.id}) + val = fn(req.args, {'dom': self.dom.name}) return val def op_maxmem_set(self, op, req): fn = FormFn(self.xd.domain_maxmem_set, - [['dom', 'int'], + [['dom', 'str'], ['memory', 'int']]) - val = fn(req.args, {'dom': self.dom.id}) + val = fn(req.args, {'dom': self.dom.name}) return val + def op_device_create(self, op, req): + fn = FormFn(self.xd.domain_device_create, + [['dom', 'str'], + ['config', 'sxpr']]) + d = fn(req.args, {'dom': self.dom.name}) + return d + + def op_device_destroy(self, op, req): + fn = FormFn(self.xd.domain_device_destroy, + [['dom', 'str'], + ['type', 'str'], + ['idx', 'str']]) + val = fn(req.args, {'dom': self.dom.name}) + return val + def op_vifs(self, op, req): - return self.xd.domain_vif_ls(self.dom.id) + devs = self.xd.domain_vif_ls(self.dom.name) + return [ dev.sxpr() for dev in devs ] def op_vif(self, op, req): fn = FormFn(self.xd.domain_vif_get, - [['dom', 'int'], - ['vif', 'int']]) - val = fn(req.args, {'dom': self.dom.id}) + [['dom', 'str'], + ['vif', 'str']]) + val = fn(req.args, {'dom': self.dom.name}) return val def op_vbds(self, op, req): - return self.xd.domain_vbd_ls(self.dom.id) + devs = self.xd.domain_vbd_ls(self.dom.name) + return [ dev.sxpr() for dev in devs ] def op_vbd(self, op, req): fn = FormFn(self.xd.domain_vbd_get, - [['dom', 'int'], - ['vbd', 'int']]) - val = fn(req.args, {'dom': self.dom.id}) - return val - - def op_vbd_add(self, op, req): - fn = FormFn(self.xd.domain_vbd_add, - [['dom', 'int'], - ['uname', 'str'], - ['dev', 'str'], - ['mode', 'str']]) - val = fn(req.args, {'dom': self.dom.id}) - return val - - def op_vbd_remove(self, op, req): - fn = FormFn(self.xd.domain_vbd_remove, - [['dom', 'int'], - ['dev', 'str']]) - val = fn(req.args, {'dom': self.dom.id}) + [['dom', 'str'], + ['vbd', 'str']]) + val = fn(req.args, {'dom': self.dom.name}) return val def render_POST(self, req): diff --git a/tools/python/xen/xend/server/SrvDomainDir.py b/tools/python/xen/xend/server/SrvDomainDir.py index 130072c871..cc41c78c61 100644 --- a/tools/python/xen/xend/server/SrvDomainDir.py +++ b/tools/python/xen/xend/server/SrvDomainDir.py @@ -24,7 +24,7 @@ class SrvDomainDir(SrvDir): def domain(self, x): val = None - dom = self.xd.domain_get(x) + dom = self.xd.domain_lookup(x) if not dom: raise XendError('No such domain ' + str(x)) val = SrvDomain(dom) @@ -74,7 +74,7 @@ class SrvDomainDir(SrvDir): def _op_create_cb(self, dominfo, configstring, req): """Callback to handle deferred domain creation. """ - dom = dominfo.id + dom = dominfo.name domurl = "%s/%s" % (req.prePathURL(), dom) req.setResponseCode(http.CREATED, "created") req.setHeader("Location", domurl) @@ -112,7 +112,7 @@ class SrvDomainDir(SrvDir): return deferred def _op_restore_cb(self, dominfo, req): - dom = dominfo.id + dom = dominfo.name domurl = "%s/%s" % (req.prePathURL(), dom) req.setResponseCode(http.CREATED) req.setHeader("Location", domurl) @@ -159,12 +159,12 @@ class SrvDomainDir(SrvDir): sxp.show(domains, out=req) else: domains = self.xd.domains() - domains.sort(lambda x, y: cmp(x.id, y.id)) + domains.sort(lambda x, y: cmp(x.name, y.name)) req.write('') diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py index b411f0ca35..8bf9a90d12 100755 --- a/tools/python/xen/xend/server/blkif.py +++ b/tools/python/xen/xend/server/blkif.py @@ -215,7 +215,7 @@ class BlkDev(controller.Dev): """ def __init__(self, ctrl, vdev, mode, segment): - controller.Dev.__init__(self, ctrl) + controller.Dev.__init__(self, segment['device'], ctrl) self.vdev = vdev self.mode = mode self.device = segment['device'] @@ -227,7 +227,11 @@ class BlkDev(controller.Dev): return 'w' not in self.mode def sxpr(self): - val = ['blkdev', ['vdev', self.vdev], ['mode', self.mode] ] + val = ['blkdev', + ['idx', self.idx], + ['vdev', self.vdev], + ['device', self.device], + ['mode', self.mode]] return val def destroy(self): diff --git a/tools/python/xen/xend/server/controller.py b/tools/python/xen/xend/server/controller.py index 756a7cd64e..fdc8bfc0ac 100755 --- a/tools/python/xen/xend/server/controller.py +++ b/tools/python/xen/xend/server/controller.py @@ -327,10 +327,14 @@ class Dev: """Abstract class for a device attached to a device controller. """ - def __init__(self, controller): + def __init__(self, idx, controller): + self.idx = str(idx) self.controller = controller self.props = {} + def getidx(self): + return self.idx + def setprop(self, k, v): self.props[k] = v diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py index ec85df8f8e..cce11f621e 100755 --- a/tools/python/xen/xend/server/netif.py +++ b/tools/python/xen/xend/server/netif.py @@ -112,7 +112,7 @@ class NetDev(controller.Dev): """ def __init__(self, ctrl, vif, config): - controller.Dev.__init__(self, ctrl) + controller.Dev.__init__(self, vif, ctrl) self.vif = vif self.evtchn = None self.configure(config) @@ -140,7 +140,10 @@ class NetDev(controller.Dev): def sxpr(self): vif = str(self.vif) mac = self.get_mac() - val = ['vif', ['idx', vif], ['mac', mac]] + val = ['vif', + ['idx', self.idx], + ['vif', vif], + ['mac', mac]] if self.bridge: val.append(['bridge', self.bridge]) if self.script: diff --git a/tools/python/xen/xend/sxp.py b/tools/python/xen/xend/sxp.py index 143ba81ab4..4fd9e9a92b 100644 --- a/tools/python/xen/xend/sxp.py +++ b/tools/python/xen/xend/sxp.py @@ -366,10 +366,11 @@ def show(sxpr, out=sys.stdout): show(x, out) i += 1 out.write(k_list_close) + elif isinstance(sxpr, (types.IntType, types.FloatType)): + out.write(str(sxpr)) elif isinstance(sxpr, types.StringType) and atomp(sxpr): out.write(sxpr) else: - #out.write("'" + str(sxpr) + "'") out.write(repr(str(sxpr))) def show_xml(sxpr, out=sys.stdout): diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index abc07fde81..e8d7957361 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -402,7 +402,7 @@ def make_domain(opts, config): except XendError, ex: opts.err(str(ex)) - dom = int(sxp.child_value(dominfo, 'id')) + dom = sxp.child_value(dominfo, 'name') console_info = sxp.child(dominfo, 'console') if console_info: console_port = int(sxp.child_value(console_info, 'console_port')) @@ -411,8 +411,8 @@ def make_domain(opts, config): if server.xend_domain_unpause(dom) < 0: server.xend_domain_destroy(dom) - opts.err("Failed to unpause domain %d" % dom) - opts.info("Started domain %d, console on port %d" + opts.err("Failed to unpause domain %s" % dom) + opts.info("Started domain %s, console on port %d" % (dom, console_port)) return (dom, console_port) diff --git a/tools/python/xen/xm/destroy.py b/tools/python/xen/xm/destroy.py index 73df69d569..812c8967df 100644 --- a/tools/python/xen/xm/destroy.py +++ b/tools/python/xen/xm/destroy.py @@ -27,14 +27,10 @@ def main(argv): return if len(args) < 1: opts.err('Missing domain') dom = args[0] - try: - domid = int(dom) - except: - opts.err('Invalid domain: ' + dom) if opts.vals.reboot: mode = 'reboot' else: mode = 'halt' - server.xend_domain_destroy(domid, mode) + server.xend_domain_destroy(dom, mode) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index d282193c43..0d53836c57 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -246,10 +246,10 @@ class ProgList(Prog): use_long = 1 if n == 0: - doms = map(int, server.xend_domains()) + doms = server.xend_domains() doms.sort() else: - doms = map(int, params) + doms = params if use_long: self.long_list(doms) @@ -257,22 +257,27 @@ class ProgList(Prog): self.brief_list(doms) def brief_list(self, doms): - print 'Dom Name Mem(MB) CPU State Time(s)' + print 'Name Id Mem(MB) CPU State Time(s) Console' for dom in doms: info = server.xend_domain(dom) d = {} - d['dom'] = int(dom) + d['dom'] = int(sxp.child_value(info, 'id', '-1')) d['name'] = sxp.child_value(info, 'name', '??') d['mem'] = int(sxp.child_value(info, 'memory', '0')) d['cpu'] = int(sxp.child_value(info, 'cpu', '0')) d['state'] = sxp.child_value(info, 'state', '??') d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0')) - print ("%(dom)-4d %(name)-16s %(mem)7d %(cpu)3d %(state)5s %(cpu_time)7.1f" % d) + console = sxp.child(info, 'console') + if console: + d['port'] = sxp.child_value(console, 'console_port') + else: + d['port'] = '' + print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3d %(state)5s %(cpu_time)7.1f %(port)4s" + % d) def long_list(self, doms): for dom in doms: info = server.xend_domain(dom) - print '\nDomain %d' % dom PrettyPrint.prettyprint(info) xm.prog(ProgList) diff --git a/tools/python/xen/xm/shutdown.py b/tools/python/xen/xm/shutdown.py index 926aaf27f3..a36c1a6b90 100644 --- a/tools/python/xen/xm/shutdown.py +++ b/tools/python/xen/xm/shutdown.py @@ -9,6 +9,8 @@ import time from xen.xend.XendClient import server from xen.xm.opts import * +DOM0 = 'Domain-0' + gopts = Opts(use="""[options] [DOM] Shutdown one or more domains gracefully. @@ -35,11 +37,9 @@ gopts.opt('reboot', short='R', use='Shutdown and reboot.') def shutdown(opts, doms, mode, wait): - def domains(): - return [ int(a) for a in server.xend_domains() ] - if doms == None: doms = domains() - if 0 in doms: - doms.remove(0) + if doms == None: doms = server.xend_domains() + if DOM0 in doms: + doms.remove(DOM0) for d in doms: server.xend_domain_shutdown(d, mode) if wait: @@ -50,7 +50,7 @@ def shutdown(opts, doms, mode, wait): if d in alive: continue dead.append(d) for d in dead: - opts.info("Domain %d terminated" % d) + opts.info("Domain %s terminated" % d) doms.remove(d) time.sleep(1) opts.info("All domains terminated") @@ -76,13 +76,8 @@ def main_all(opts, args): def main_dom(opts, args): if len(args) < 1: opts.err('Missing domain') dom = args[0] - try: - domid = int(dom) - except: - opts.err('Invalid domain: ' + dom) - mode = shutdown_mode(opts) - shutdown(opts, [ domid ], mode, opts.vals.wait) + shutdown(opts, [ dom ], mode, opts.vals.wait) def main(argv): opts = gopts @@ -90,7 +85,6 @@ def main(argv): if opts.vals.help: opts.usage() return - print 'shutdown.main>', len(args), args if opts.vals.all: main_all(opts, args) else: -- 2.30.2